package edu.kit.csl.cratylus.extraction.elki;

import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.IntegerDistance;
import edu.kit.csl.cratylus.datatypes.Candidate;
import edu.kit.csl.cratylus.extraction.LevenshteinUtils;

/**
 * We provide ELKI a customized distance function in order to deal with
 * phoneme sequences (i.e. strings containing blank separated phonemes). The
 * implemented distance metric is the relative Levenshtein distance. It is 
 * defined as the Levenshtein distance divided by the length of the first
 * phoneme sequence. We multiply by 100 to obtain an integer distance.
 * 
 * @see LevenshteinUtils
 */
public class RelativeLevenshteinDistanceFunction extends
		AbstractPrimitiveDistanceFunction<ElkiCandidate, IntegerDistance> {

	/**
	 * Only accepts {@link ElkiCandidate} instances.
	 * {@inheritDoc}
	 */
	@Override
	public SimpleTypeInformation<? super ElkiCandidate> 
				getInputTypeRestriction() {
		return new SimpleTypeInformation<ElkiCandidate>(ElkiCandidate.class);
	}

	/**
	 * Calculates the relative Levenshtein distance between two phoneme 
	 * sequences using dynamic programming and the length of {@code o1}. We 
	 * multiply by 100 to obtain an integer distance. If both candidates are 
	 * from the same sentence pair, but on another position, return 1000.
	 * 
	 * @param o1 first phoneme sequence
	 * @param o2 second phoneme sequence to compare with the {@code o1}
	 * @return the relative Levenshtein distance between {@code o1} and 
	 * 			{@code o2}
	 * @throws NullPointerException if one of the arguments or their content
	 * 				is null
	 * @see LevenshteinUtils#distance(String[], String[])
	 */
	@Override
	public IntegerDistance distance(ElkiCandidate o1, ElkiCandidate o2) {
		Candidate c1 = o1.getValue(0);
		Candidate c2 = o2.getValue(0);
		String[] str1 = c1.getWord().getContent().split(" ");
		String[] str2 = c2.getWord().getContent().split(" ");
		/*if (c1.getPair().getTargetSentence() 
				== c2.getPair().getTargetSentence()) {
			return new IntegerDistance(c1.getPosition() != c2.getPosition() ?
					1000 : 0);
		}*/
		return new IntegerDistance(
				100 * LevenshteinUtils.distance(str1, str2) /
				str1.length);
	}

	@Override
	public IntegerDistance getDistanceFactory() {
		return IntegerDistance.FACTORY;
	}
}
